package com.example.auv_660.network.tcp;

import com.example.auv_660.moduleload.ModuleLoad;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.ArrayList;
import java.util.ServiceLoader;

public enum HFTCPBuild {
    INSTANCE;

    private HFTCPServer hftcpServer;

    HFTCPBuild()
    {
        hftcpServer = new HFTCPServer();
    }

    public HFTCPServer getHFTcpServer()
    {
        return hftcpServer;
    }

    private static ArrayList<ModuleLoad> instances;

    static
    {
        // ServiceLoader.load执行时，会到META-INF/services的配置文件中寻找这个接口对应得实现类的全路径名，然后使用反射去生成一个无参的实例
        ServiceLoader<ModuleLoad> serviceLoader = ServiceLoader.load(ModuleLoad.class);
        instances = new ArrayList<>();

        for (ModuleLoad service : serviceLoader)
        {
            instances.add(service);
        }

        for (int i = 0; i < instances.size() - 1; i++)
        {
            instances.get(i).setNextModule(instances.get(i + 1));
        }
    }

    public ArrayList<ModuleLoad> getModuleInstance()
    {
        return instances;
    }

    public class HFTCPServer
    {
        private static final int TCP_SERVER_PORT = 30001;
        private AsynchronousServerSocketChannel asynchronousServerSocketChannel;

        private HFTCPServer()
        {

        }

        private void enableTCPResource()
        {
            try
            {
                asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
                asynchronousServerSocketChannel.bind(new InetSocketAddress(TCP_SERVER_PORT), 5);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }

        public void tcpWorker()
        {
            enableTCPResource();
            enableConnHandler();
        }

        private void enableConnHandler() {
            if (asynchronousServerSocketChannel == null) {
                releaseTCPResource();
                System.out.println("Can't enable TCP socket Channel");
                return;
            }

            if (instances.size() == 0) {
                releaseTCPResource();
                System.out.println("Can't load ModuleLoad instance");
                return;
            }

            ModuleConnHandler connHandler = new ModuleConnHandler();
            getAsynchronousServerSocketChannel().accept(connHandler, connHandler);
        }

        private void releaseTCPResource() {

            if (asynchronousServerSocketChannel != null) {
                try {
                    asynchronousServerSocketChannel.close();
                    asynchronousServerSocketChannel = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            instances.clear();
        }

        public AsynchronousServerSocketChannel getAsynchronousServerSocketChannel() {
            return asynchronousServerSocketChannel;
        }
    }
}
